package com.example.chuzhou.util;


import com.example.chuzhou.sm2.SM2EncDecUtils;
import com.example.chuzhou.sm2.Util;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

public class SM2Util {

    static final String PRIVATE_KEY = "fba2dc188e2c1765ca7081a987af2cac92cce640ff46b06a7929e1a277d2ab52";

    static final String PUBLIC_KEY = "041eab0797f1fc3a88ee89defbf18bceaeb2d890e257d08e2417dd9a78e363be0778516807a6fcc0016f985094b3d580038fac11819edbb36f03091d5a0feb50f2";

    static ECDomainParameters domainParameters;

    static AsymmetricCipherKeyPair asymmetricCipherKeyPair;

    static {
        X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
        domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());
        ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
        try {
            keyPairGenerator.init((new ECKeyGenerationParameters(domainParameters, SecureRandom.getInstance("SHA1PRNG"))));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        asymmetricCipherKeyPair = keyPairGenerator.generateKeyPair();
    }

    /**
     * 生成密钥对
     */
    public static void generateKeyPair() {

        //私钥，16进制格式，自己保存，格式如a2081b5b81fbea0b6b973a3ab6dbbbc65b1164488bf22d8ae2ff0b8260f64853
        BigInteger privatekey = ((ECPrivateKeyParameters) asymmetricCipherKeyPair.getPrivate()).getD();
        String privateKeyHex = privatekey.toString(16);
        System.out.println("privateKeyHex = " + privateKeyHex);
        //公钥，16进制格式，发给前端，格式如04813d4d97ad31bd9d18d785f337f683233099d5abed09cb397152d50ac28cc0ba43711960e811d90453db5f5a9518d6608
        ECPoint ecPoint = ((ECPublicKeyParameters) asymmetricCipherKeyPair.getPublic()).getQ();
        String publicKeyHex = Hex.toHexString(ecPoint.getEncoded(false));
        System.out.println("publicKeyHex = " + publicKeyHex);
    }


    public static String decrypt(String cipherData) throws InvalidCipherTextException, UnsupportedEncodingException {
        //JS加密产生的密文
        byte[] cipherDataByte = Hex.decode(cipherData);
        //刚才的私钥Hex，先还原私钥
        BigInteger privateKeyD = new BigInteger(PRIVATE_KEY, 16);
        ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(privateKeyD, domainParameters);
        //用私钥解密
        SM2Engine sm2Engine = new SM2Engine();
        sm2Engine.init(false, privateKeyParameters);
        //processBlock得到Base64格式，记得解码
        byte[] arrayOfBytes = Base64.getDecoder().decode(sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length));
        //得到明文：SM2 Encryption Test
        return new String(arrayOfBytes, StandardCharsets.UTF_8);
    }


    public static String decrypt2(String cipherData) throws IOException {
        byte[] bytes1 = Util.hexToByte(PRIVATE_KEY);
        byte[] bytes2 = Util.hexToByte(cipherData);
        byte[] decrypt = SM2EncDecUtils.decrypt(bytes1, bytes2);
        String s = new String(decrypt, StandardCharsets.UTF_8);
        return s;
    }
}
